<script setup lang="ts">
import {
  ArrowDown,
  CaretLeft,
  CaretRight,
  Headset,
  VideoPause,
  VideoPlay,
} from "@element-plus/icons-vue";
import { onActivated, onDeactivated, reactive, ref, unref, watch } from "vue";
import { Howl } from "howler";
import { formatTrackTime } from "@/utils";
import { Local } from "@/utils/storage";
import { audioHistoryStorage } from "@/storage";
import { defaultAudioHistoryStorage } from "@/storage/defaults";
import { useIntervalFn } from "@vueuse/core";

const loading = ref(false);
const playing = ref(false);

const options = [
  { label: "热歌榜", value: "热歌榜" },
  { label: "新歌榜", value: "新歌榜" },
  { label: "飙升榜", value: "飙升榜" },
  { label: "原创榜", value: "原创榜" },
];

// 当前播放
const state = reactive<AudioType>(
  Local.get("home_audio") || defaultAudioHistoryStorage()[0]
);

const volume = ref(100);
const current = ref(0);
const duration = ref(0);
const currentTime = ref("00:00");
const durationTime = ref("00:00");

let sound: Howl;

const { pause, resume } = useIntervalFn(() => {
  if (sound) {
    playing.value = sound.playing();
    current.value = Math.ceil(sound.seek());
    duration.value = Math.ceil(sound.duration());
    currentTime.value = formatTrackTime(unref(current));
    durationTime.value = formatTrackTime(unref(duration));
  }
}, 1000);

const onPause = () => {
  if (!sound) {
    onPlay();
  } else {
    if (playing.value) {
      sound.pause();
      pause();
    } else {
      sound.play();
      resume();
    }
  }
};

const onPlay = async () => {
  loading.value = true;

  // 回收所有播放的进程
  Howler.unload();

  // 初始化播放
  sound = new Howl({
    src: [state.url],
    html5: true,
    autoplay: true,
    volume: unref(volume) / 100,
    format: ["mp3", "acc", "flac"],
  });
  sound.on("loaderror", (soundId, error) => {
    if (error === 4) {
      onNext();
      console.log("无法播放: 不支持的音频格式");
    } else {
      console.log("Error", soundId, error);
    }
    loading.value = false;
  });

  sound.on("play", () => {
    playing.value = true;
  });

  sound.on("pause", () => {
    playing.value = false;
  });

  sound.once("load", () => {
    loading.value = false;
    plusHistory();
  });
  sound.once("end", () => {
    playing.value = false;
    // 下一首
    onNext();
  });
};

const onNext = async () => {
  loading.value = true;
  const { info, sort } = await fetch(
    `https://api.vvhan.com/api/wyMusic/${state.sort}?type=json`
  ).then((res) => res.json());
  setState(info, sort);
  await onPlay();
};

const setState = (info: AudioType, sort?: string) => {
  state.sort = sort || info.sort;
  state.id = info.id;
  state.name = info.name;
  state.auther = info.auther;
  state.url = info.url;
  state.picUrl = info.picUrl || info.pic_url || "";
  Local.set("home_audio", state);
};

const plusHistory = () => {
  if (!audioHistoryStorage.value.some((s) => s.id === state.id)) {
    audioHistoryStorage.value.unshift(JSON.parse(JSON.stringify(state)));
  }
};

const formatTooltip = (value: number) => {
  return value + "%";
};

const formatTooltip2 = (value: number) => {
  return formatTrackTime(value);
};

const onSliderChange = (value: number) => {
  sound?.seek(value);
};

const onCommand = (id: number) => {
  const item = audioHistoryStorage.value.find((f) => f.id === id);
  if (item) {
    playing.value = false;
    setState(item);
    onPlay();
  }
};

watch(volume, (value) => {
  sound?.volume(value / 100);
});

onActivated(() => {
  resume();
});

onDeactivated(() => {
  pause();
});
</script>

<template>
  <div
    class="home-audio h100 color-white"
    :style="{ backgroundImage: `url(${state.picUrl})` }"
  >
    <div class="home-audio-mask"></div>
    <div class="home-audio-content flex flex-column px5 pt5">
      <div
        class="w100 flex align-center justify-between home-audio-content-select"
      >
        <el-select v-model="state.sort">
          <el-option
            v-for="(item, index) in options"
            :key="index"
            :value="item.value"
            :label="item.label"
          ></el-option>
        </el-select>
        <el-dropdown trigger="click" @command="onCommand">
          <el-button>
            历史记录 [{{ audioHistoryStorage.length }}]
            <el-icon class="el-icon--right">
              <ArrowDown />
            </el-icon>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu style="max-height: 50vh">
              <el-dropdown-item
                v-for="(item, index) in audioHistoryStorage"
                :key="index"
                :command="item.id"
                :disabled="item.id === state.id"
              >
                《{{ item.name }}》{{ item.auther }}
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
      <div class="mb5 font-bold font18 mt-auto">{{ state.name }}</div>
      <div>{{ state.auther }}</div>
      <div class="my10">
        <el-button
          :disabled="loading"
          :icon="CaretLeft"
          circle
          class="font24 pa5 width-auto height-auto"
          @click="onNext"
        ></el-button>
        <el-button
          v-if="!playing"
          :loading="loading"
          :icon="VideoPlay"
          circle
          type="primary"
          class="font50 pa2 width-auto height-auto ml20"
          @click="onPause"
        ></el-button>
        <el-button
          v-else
          :loading="loading"
          :icon="VideoPause"
          circle
          type="danger"
          class="font50 pa2 width-auto height-auto ml20"
          @click="onPause"
        ></el-button>
        <el-button
          :disabled="loading"
          :icon="CaretRight"
          circle
          class="font24 pa5 width-auto height-auto ml20"
          @click="onNext"
        ></el-button>
      </div>
      <div class="flex justify-between">
        <span>来一首歌放松心情吧~</span>
        <div class="flex align-center justify-center">
          <div
            style="width: 80px; transform: translateX(-10px)"
            class="flex align-center"
          >
            <el-icon>
              <Headset />
            </el-icon>
            <el-slider
              v-model="volume"
              :step="1"
              :min="0"
              :max="100"
              class="ml5"
              :format-tooltip="formatTooltip"
            />
          </div>
        </div>
      </div>
      <div class="flex align-center mb10">
        <span class="mr10">{{ currentTime }}</span>
        <el-slider
          v-model="current"
          :min="0"
          :max="duration"
          :format-tooltip="formatTooltip2"
          @change="onSliderChange"
        />
        <span class="ml10">{{ durationTime }}</span>
      </div>
    </div>
  </div>
</template>
<style lang="scss">
.home-audio {
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center center;
  position: relative;

  &:hover {
    .home-audio-mask {
      background-color: rgba(0, 0, 0, 0.7);
    }
  }

  .home-audio-mask {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.4);
    transition: background-color ease-in-out 0.3s;
    z-index: 0;
  }

  .home-audio-content {
    position: relative;
    z-index: 1;
    width: 100%;
    height: 100%;

    .home-audio-content-select {
      .el-select {
        width: 100px;
      }

      .el-button {
        color: #ededed !important;
        background-color: transparent !important;
        border-color: #ededed !important;
      }

      .el-select__wrapper {
        background-color: transparent !important;
        box-shadow: 0 0 0 1px #ededed inset;
      }

      .el-select__caret,
      .el-select__placeholder {
        color: #ededed !important;
      }
    }
  }
}
</style>
